
/**
 * Temporary class to preload stream data, will be integrated into JorbisAudio later.
 */

package com.servequake.truemusic;

import java.io.*;

import com.jcraft.jorbis.*;
import com.jcraft.jogg.*;

class VorbisPrimer
{
	InputStream bitStream = null;

	static final int BUFSIZE=4096*2;
	static int convsize=BUFSIZE*2;

	SyncState oy;
	StreamState os;
	Page og;
	Packet op;
	Info vi;
	Comment vc;
	DspState vd;
	Block vb;
  
	byte[] buffer=null;
	int bytes=0;

	int format;
	int rate=0;
	int channels=0;

	int frameSizeInBytes;
	int bufferLengthInBytes;

	String title="";
	String artist="";
	String album="";
	String track="";
	String lyrics="";

	int frames = 0;

	VorbisPrimer(String res) throws Exception
	{
    int last_channels=-1;
    int last_rate=-1;

    boolean chained=false;

		oy=new SyncState();
		os=new StreamState();
		og=new Page();
		op=new Packet();
		vi=new Info();
		vc=new Comment();
		vd=new DspState();
		vb=new Block(vd);
  
		buffer=null;
		bytes=0;

		oy.init();

try
{
		bitStream = new FileInputStream(res);
}catch(Exception e){return;}

			top:
		while(true)
		{
				int eos = 0;

				int index = oy.buffer(BUFSIZE);
				buffer = oy.data;

				try{ bytes = bitStream.read(buffer,index, BUFSIZE); }
				catch(Exception e) { return; }

				oy.wrote(bytes);
	
				if(chained) chained=false;
				else
				{
					if(oy.pageout(og)!=1)
					{
						if(bytes<BUFSIZE) break;

						System.err.println("Input does not appear to be an Ogg bitstream.");
						throw new Exception();

					}
				}

				os.init(og.serialno());
				os.reset();

				vi.init();
				vc.init();

				if(os.pagein(og)<0)
				{
					System.err.println("Error reading first page of ogg bitstream data.");
											throw new Exception();

				}

				if(os.packetout(op)!=1)
				{
					System.err.println("Error reading initial header packet");
											throw new Exception();

				}

				if(vi.synthesis_headerin(vc, op)<0)
				{
					System.err.println("This ogg bitstream does not contain vorbis audio data");
											throw new Exception();

				}

				int i = 0;

				while(i<2)
				{
					while(i<2)
					{
						int result = oy.pageout(og);
						if(result==0) break; //need more data
						if(result==1)
						{
							os.pagein(og);
							while(i<2)
							{
								result = os.packetout(op);
								if(result==0) break;
								if(result==-1)
								{
									System.err.println("corrupt secondary header. exiting.");
									throw new Exception();
								}
								vi.synthesis_headerin(vc, op);
								i++;
							}
						}
					}

					index = oy.buffer(BUFSIZE);
					buffer = oy.data;
	
					try{ bytes = bitStream.read(buffer,index, BUFSIZE); }
					catch(Exception e)
					{
						e.printStackTrace();
						throw new Exception();
					}
	
					if(bytes==0 && i<2)
					{
						System.err.println("End of file before finding all Vorbis headers!");
						throw new Exception();
					}

					oy.wrote(bytes);
				} // end header loops?

	
			

				//System.out.println(vc.toString());
			title = vc.query("title"); //appears to be case insensetive?
			artist = vc.query("artist");
			album = vc.query("album");
			track = vc.query("track");
			lyrics = vc.query("lyrics");
		if(title==null)title="";
			if(artist==null)artist="";
			if(album==null)album="";
			if(track==null)track="";
			if(lyrics==null)lyrics="";
						
				convsize=BUFSIZE/vi.channels;

				vd.synthesis_init(vi);
				vb.init(vd);

				double[][][] _pcm = new double[1][][];
				float[][][] _pcmf = new float[1][][];
				int[] _index = new int[vi.channels];

				//getOutputLine(vi.channels, vi.rate);

			while(eos==0)
			{

				while(eos==0) 
				{

					
					int result = oy.pageout(og);
					if(result == 0) break; //need more data
					if(result==-1){} // missing or corrupt data at this page position, continuing...
					else
					{
						os.pagein(og);

						if(og.granulepos()==0)
						{
							chained=true;
							eos=1;
							break;
						}
	
						while(true)
						{
							result = os.packetout(op);
							if(result==0) break; //need more data
							if(result==-1)
							{//missing or corrupt data, already complained above
							}
							else
							{
								frames++;

								//we have a packet. Decode it
								int samples;
							//	if(vb.synthesis(op)==0){ //test for success!
						  	//		vd.synthesis_blockin(vb);
							//	}

							//	while( (samples=vd.synthesis_pcmout(_pcmf, _index))>0 )
							//	{
									
							//			double[][] pcm = _pcm[0];
							//			float[][] pcmf = _pcmf[0];

							//			boolean clipflag=false;
							//			int bout = (samples<convsize?samples:convsize);

							
							//			vd.synthesis_read(bout);

							//			frames++;
									
							//	}//while samples
							}//else have a packet
							if(og.eos()!=0)eos=1;
						}
					}
				}//inner playloop


				if(eos==0)
				{
					index=oy.buffer(BUFSIZE);
					buffer=oy.data;
					try
					{
						bytes=bitStream.read(buffer,index,BUFSIZE);
					}
					catch(Exception e)
					{
						System.err.println(e);
            				throw new Exception();
					}
          
					if(bytes==-1)
					{
            				//System.err.println("bytes==-1");
            				break;
	 				}
	  				oy.wrote(bytes);
	  				if(bytes==0)eos=1;
        			}


			}// outer play loop

      		os.clear();
      		vb.clear();
      		vd.clear();
      		vi.clear();
		}

		oy.clear();				
		
		
    		try {
			if(bitStream!=null)bitStream.close();
		} 
		catch(Exception e) { }
	}
}
